#include <math.h>
#include "Vector2D.h"


Vector2D::Vector2D()
{
	x=0.0;
	y=0.0;
}
Vector2D::Vector2D(float x0, float y0)
{
	x = x0;
	y = y0;
}
	
	// Addition/subtraction
Vector2D Vector2D::operator+(Vector2D other) const
{
	return Vector2D(x + other.x, y + other.y);
}
	//friend Vector3D operator+(Vector3D a, Vector3D &b);
Vector2D Vector2D::operator-(Vector2D other)
{
	return Vector2D(x - other.x, y - other.y);
}
bool Vector2D::operator==(Vector2D other)
{
	return (this->x == other.x) && (this->y == other.y);
}
	//Multiplication by number
Vector2D Vector2D::operator*(float k)
{
	return Vector2D(k * x, k * y);
}
Vector2D Vector2D::operator/(float k)
{
	return Vector2D(x/k, y/k);
}
Vector2D operator*(float k, Vector2D &other)
{
	return Vector2D(k * other.x, k * other.y);
}

	//Inner product
float Vector2D::operator*(Vector2D other)
{
	return (x * other.x + y * other.y);
}
	
	//Normalization
Vector2D Vector2D::operator!()
{
	return *this/this->Magnitude();
}
    //Distance (for 2D points)
float Vector2D::operator|(Vector2D other)
{
	float dx = x - other.x;
	float dy = y - other.y;
	return sqrt(dx * dx + dy * dy);
}

	
	//Square Distance (for 2D points) (sometimes helps reduce many SQRTs)
float Vector2D::operator ||(Vector2D other)
{
	float dx = x - other.x;
	float dy = y - other.y;
	return dx*dx + dy*dy;
}

Vector2D& Vector2D::operator *=(float k)
{
	x *= k;
	y *= k;
	return *this;
}

float Vector2D::Magnitude(void)
{
	return sqrt(x * x + y * y);
}


void Vector2D::add(Vector2D other)
{
	x += other.x;
	y += other.y;
}
void Vector2D::subtract(Vector2D other)
{
	x -= other.x;
	y -= other.y;
}
	
void Vector2D::negate()
{
	x = -x;
	y = -y;
}

void Vector2D::mul(float k)
{
	x *= k;
	y *= k;
}
float Vector2D::dot(Vector2D other)
{
	return x*other.x + y*other.y;
}

float Vector2D::dist(Vector2D other)
{
	return *this|other;
}
float Vector2D::sqdist(Vector2D other)
{
	return *this||other;
}
float Vector2D::AngleDirection(Vector2D other)
{
	return this->x * other.y - this->y * other.x;
}
float Vector2D::PointToLineDistance(Vector2D &point, Vector2D &endPoint1, Vector2D &endPoint2)
{
	return (point | ClosestPointOnSegment(endPoint1, endPoint2, point));	
}
Vector2D Vector2D::ClosestPointOnSegment(Vector2D& A, Vector2D& B, Vector2D& P)
{
    Vector2D D = B-A;
    float numer = (P-A).dot(D);
    if (numer <= 0.0f)
        return A;
    float denom = D.dot(D);
    if (numer >= denom)
        return B;
    return A + (numer/denom) * D;
}	
bool Vector2D::SegmentsIntersect(Vector2D a, Vector2D b, Vector2D c, Vector2D d)
{
	float denom = ((d.y -c.y)*(b.x - a.x) - (d.x - c.x)*(b.y - a.y));
	if(denom == 0)
		return false;
		
	float ua = ((d.x - c.x)*(a.y - c.y) - (d.y - c.y)*(a.x - c.x))/denom;
	float ub = ((b.x - a.x)*(a.y- c.y) - (b.y - a.y)*(a.x - c.x))/denom;

	return (ua >= 0) && (ua <= 1) && (ub >= 0) && (ub <= 1);
}